﻿using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace Helpers.Serialization
{
    public class XmlSerializer<T>
    {
        #region Properties

        private T source;

        #endregion

        public XmlSerializer(T source)
        {
            this.source = source;
        }

        #region Methods

        /// <summary>
        /// Parses the current status of the source object to an xml string.
        /// </summary>
        /// <returns>An string with the xml file.</returns>
        public virtual string GetXml()
        {
            return XmlSerializer.GetXml(this.source);
        }
        //public T Load(string fileName)
        //{
        //    System.Xml.Serialization.XmlSerializer mySerializer = new System.Xml.Serialization.XmlSerializer(typeof(T));
        //    FileStream myFileStream = new FileStream(fileName, FileMode.Open);
        //    T obj = (T)mySerializer.Deserialize(myFileStream);
        //    myFileStream.Dispose();

        //    return obj;
        //}
        public virtual void Save(string fileName)
        {
            XmlSerializer.Save<T>(fileName, this.source);
        }

        #endregion
    }

    public static class XmlSerializer
    {
        #region Static Methods

        /// <summary>
        /// Parses the object specified to an xml string.
        /// </summary>
        /// <returns>An string with the xml file.</returns>
        public static string GetXml(object obj)
        {
            MemoryStream ms = new MemoryStream();

            //XmlTextWriter xmlWriter;
            //xmlWriter = new XmlTextWriter(ms, Encoding.UTF8);

            /* Creates our own namespaces for the output. */
            XmlSerializerNamespaces ns = new XmlSerializerNamespaces();

            /* Adds an empty namespace and empty value. */
            ns.Add("", "");

            /* Configures the xml writer. */
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.OmitXmlDeclaration = true;
            settings.Encoding = new UTF8Encoding(false);
            settings.Indent = true;
            settings.IndentChars = "    ";
            settings.NewLineHandling = NewLineHandling.Replace;
            settings.NewLineChars = "\r\n";
            settings.NewLineOnAttributes = true;

            /* Creates xml with the object to serrialize. */
            XmlWriter xml = XmlWriter.Create(ms, settings);

            System.Xml.Serialization.XmlSerializer mySerializer =
                new System.Xml.Serialization.XmlSerializer(obj.GetType());

            mySerializer.Serialize(xml, obj, ns);

            /* Returns the xml string with the object serialized. */
            return Encoding.UTF8.GetString(ms.GetBuffer());
        }
        public static T LoadFromXmlString<T>(string xml)
        {
            //Returns an instance of the type serialized.
            return (T)XmlSerializer.LoadFromXmlString(xml, typeof(T));
        }
        public static object LoadFromXmlString(string xml, Type type)
        {
            /* Initializes XmlSerializer with the type of this class. */
            System.Xml.Serialization.XmlSerializer mySerializer = new System.Xml.Serialization.XmlSerializer(type);

            StringReader stringReader = new StringReader(xml);

            XmlReader xmlReader = XmlReader.Create(stringReader);

            /* Returns an instance of the type serialized. */
            return mySerializer.Deserialize(xmlReader);
        }
        public static T LoadFromFile<T>(string fileName)
        {
            return (T)XmlSerializer.LoadFromFile(fileName, typeof(T));
        }
        public static object LoadFromFile(string fileName, Type type)
        {
            System.Xml.Serialization.XmlSerializer mySerializer = new System.Xml.Serialization.XmlSerializer(type);
            FileStream myFileStream = new FileStream(fileName, FileMode.Open);

            object objLoaded = mySerializer.Deserialize(myFileStream);

            myFileStream.Dispose();

            return objLoaded;
        }
        public static void Save<T>(string fileName, T obj)
        {
            XmlSerializer.Save(fileName, obj, typeof(T));
        }
        public static void Save(string fileName, object obj, Type type)
        {
            System.Xml.Serialization.XmlSerializer mySerializer = new System.Xml.Serialization.XmlSerializer(type);
            StreamWriter myWriter = new StreamWriter(fileName);

            mySerializer.Serialize(myWriter, obj);

            myWriter.Dispose();
        }

        #endregion
    }
}